package com.sikaryofficial.workbench.utils.excel.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.metadata.data.CellData;
import com.alibaba.excel.read.metadata.holder.ReadSheetHolder;
import com.sikaryofficial.common.core.exception.ServiceException;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 数据格式校验，数据内容校验
 * @param <T>
 */
@Slf4j
public class ImportListener<T> extends AnalysisEventListener<T> {

    @Getter
    private final List<T> list = new ArrayList<>();

    private Map<Integer,String> headMap;

    @Override
    public void invoke(T data, AnalysisContext context) {
        String errMsg = ValidateUtil.validateEntity(data);
        if (StringUtils.isNotBlank(errMsg)) {
            // 这里异常，依然属于解析异常，会在 onException 中处理，因此不用设置行列信息
            throw new ServiceException(errMsg);
        }
        list.add(data);
    }

    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        log.warn("excel读取异常", exception);

        // 行信息从sheet中读取。列信息根据不同的实现，有不同的存储位置，所以放在别的地方获取
        final ReadSheetHolder readSheetHolder = context.readSheetHolder();
        Integer rowNum = readSheetHolder.getRowIndex();
//        final Integer headRowNumber = readSheetHolder.getHeadRowNumber();
//        int index = rowNum - headRowNumber;

        throw new ServiceException("Excel内容有错误，第" + rowNum + "行：" + extractInfoFromException(exception));
    }

    private String extractInfoFromException(Exception exception) {
        if (exception instanceof ExcelDataConvertException) {
            return convertException((ExcelDataConvertException) exception);
        }
        final Throwable cause = exception.getCause();
        if (cause != null) {
            return cause.getMessage();
        } else {
            return exception.getMessage();
        }
    }

    private String convertException(ExcelDataConvertException exception) {
        final Integer columnIndex = exception.getColumnIndex();
        // 如果是合并单元格，会读取不到头部，因此直接使用列来代替
//        final String headName = headMap.get(columnIndex);
        final CellData<?> cellData = exception.getCellData();
        // 暂时不提取java数据类型，只提示格式有误。java相关信息可以从 excelContentProperty.getHead() 中提取
        return "[" + (columnIndex + 1) + "]列数据解析失败[" + cellData.getStringValue() + "]";
    }

    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        this.headMap = headMap;
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {

    }

}
